# -*- coding: UTF-8 -*-
from __future__ import print_function

from enum import Enum


EventType = Enum("EventType", "TICK BAR SIGNAL ORDER FILL")


class Event(object):
    """
    Event 是一个事件基类，给事件子类提供方法接口，子类事件会在交易过程中
    产生并且传递.
    """
    @property
    def typename(self):
        return self.type.name


class TickEvent(Event):
    """
    当市场行情产生一个tick数据时候就会触发tick事件
    """
    def __init__(self, ticker, time, bid, ask, bid_volume, ask_volume):
        """
        TickEvent初始化

        Parameters:
        ticker - 交易代码, e.g. 'AU1707'
        time - tick的datetime
        bid - 卖盘最优价格
        ask - 买盘最优价格
        volume - 每一个tick的成交量
        """
        self.type = EventType.TICK
        self.ticker = ticker
        self.time = time
        self.bid = bid
        self.ask = ask
        self.bid_volume = bid_volume
        self.ask_volume = ask_volume

    def __str__(self):
        return "Type: %s, Ticker: %s, Time: %s, Bid: %s, Ask: %s" % (
            str(self.type), str(self.ticker),
            str(self.time), str(self.bid), str(self.ask)
        )

    def __repr__(self):
        return str(self)


class BarEvent(Event):
    """
    当从行情接口收集足一个OHLC(开盘价，最高价，最低价，收盘价)的K线柱时，
    触发BarEvent，回测时由历史数据提供接口触发
    """
    def __init__(
        self, ticker, time, period,
        open_price, high_price, low_price,
        close_price, volume, adj_close_price=None
    ):
        """
        初始化 BarEvent.

        Parameters:
        ticker - 交易代码, e.g. 'AU1707'
        time - Bar数据的时间戳
        period - Bar的时间周期，单位秒
        open_price - 开盘价
        high_price - 最高价
        low_price - 最低价
        close_price - 收盘价
        volume - 成交量
        adj_close_price - 除权收盘价

        """
        self.type = EventType.BAR
        self.ticker = ticker
        self.time = time
        self.period = period
        self.open_price = open_price
        self.high_price = high_price
        self.low_price = low_price
        self.close_price = close_price
        self.volume = volume
        self.adj_close_price = adj_close_price
        self.period_readable = self._readable_period()

    def _readable_period(self):
        """
        通过时间周期（秒数）生成人性化可读的周期

        例如:
        * 1 -> '1sec'
        * 5 -> '5secs'
        * 60 -> '1min'
        * 300 -> '5min'

        如果事件周期在lut中没有定义将生成秒为单位的可读性字符串
        """
        lut = {
            1: "1sec",
            5: "5sec",
            10: "10sec",
            15: "15sec",
            30: "30sec",
            60: "1min",
            300: "5min",
            600: "10min",
            900: "15min",
            1800: "30min",
            3600: "1hr",
            86400: "1day",
            604800: "1wk"
        }
        if self.period in lut:
            return lut[self.period]
        else:
            return "%ssec" % str(self.period)

    def __str__(self):
        format_str = "Type: %s, Ticker: %s, Time: %s, Period: %s, " \
            "Open: %s, High: %s, Low: %s, Close: %s, " \
            "Adj Close: %s, Volume: %s" % (
                str(self.type), str(self.ticker), str(self.time),
                str(self.period_readable), str(self.open_price),
                str(self.high_price), str(self.low_price),
                str(self.close_price), str(self.adj_close_price),
                str(self.volume)
            )
        return format_str

    def __repr__(self):
        return str(self)


class SignalEvent(Event):
    """
    信号事件是由策略模块(Strategy)生成，有投资组合模块(Portfolio)接收
    """
    def __init__(self, ticker, action,amount,price):
        """
        初始化SignalEvent.

        Parameters:
        ticker - 交易代码, e.g. 'AU1707'
        action - 'BOT' (多) or 'SLD' (空).
        """
        self.type = EventType.SIGNAL
        self.ticker = ticker
        self.action = action
        self.amount = amount
        self.price = price


class OrderEvent(Event):
    """
    订单事件是发送一个订单到交易模块进行下单操作，订单事件包含交易代码ticker
    订单方向，多或空，交易数量quantity
    """
    def __init__(self, ticker, action, quantity,price):
        """
        Initialises the OrderEvent.

        Parameters:
        ticker - 交易代码, e.g. 'AU1707'
        action - 'BOT' (多) or 'SLD' (空)
        quantity - 交易数量
        """
        self.type = EventType.ORDER
        self.ticker = ticker
        self.action = action
        self.quantity = quantity
        self.price = price

    def print_order(self):
        """
        打印订单事件的内容
        """
        print(
            "Order: Ticker=%s, Action=%s, Quantity=%s" % (
                self.ticker, self.action, self.quantity
            )
        )


class FillEvent(Event):
    """
    订单成交事件是由交易接口产生，包含了实际成交数量和实际成交的价格
    另外包含交易产生的佣金税收等手续费
    """

    def __init__(
        self, ticker,
        action, quantity,
        exchange, price,
        commission
    ):
        """
        初始化订单成交事件

        timestamp - 订单成交的时间戳
        ticker - 交易代码, e.g. 'AU1707'
        action - 'BOT' (多) or 'SLD' (空)
        quantity - 成交数量
        exchange - 交易所
        price - 实际成交价格
        commission - 交易中产生的手续费
        """
        self.type = EventType.FILL
        self.ticker = ticker
        self.action = action
        self.quantity = quantity
        self.exchange = exchange
        self.price = price
        self.commission = commission
